/* =============================================================================
#     FileName: wl_ringbuff.c
#     Desc:
#     LastChange:
#     History:
============================================================================= */
#include "wl_ringbuff.h"
#include "stddef.h"
#include "stdio.h"
#include "amLog.h"


int32_t wl_ringbuf_write(Ringbuf_st* ring, uint8_t* data, uint32_t size)
{
    if (ring == NULL || data ==NULL || size == 0 || size+DMA_DATALEN_LEN > ring->u16ItemSize)
    {
        return ERR_RINGBUF_INVALID_PARAM;
    }

    if (ring->u8WritingFlag == TRUE)
    {
        return ERR_RINGBUF_WRITE_BUSY;
    }

    if (ring->u16FullFlag == TRUE)
    {
        return ERR_RINGBUF_BUF_FULL;
    }

    ring->u8WritingFlag = TRUE;
    memset((uint8_t*)&ring->ps8Buf[ring->u16WItemID*ring->u16ItemSize], 0, ring->u16ItemSize);
    memcpy((uint8_t*)&ring->ps8Buf[ring->u16WItemID*ring->u16ItemSize], (uint8_t*)&size, DMA_DATALEN_LEN);
    memcpy((uint8_t*)&ring->ps8Buf[ring->u16WItemID*ring->u16ItemSize+DMA_DATALEN_LEN], data, size);
    ring->u16WItemID = (ring->u16WItemID+1)%ring->u16Items;

    if (ring->u16WItemID == ring->u16RItemID)
    {
        ring->u16FullFlag = TRUE;
    }

    ring->leftItem = wl_ringbuf_freeSize(ring);
    if (ring->minLeftItem > ring->leftItem)
    {
        ring->minLeftItem = ring->leftItem;
    }

    ring->u8WritingFlag = FALSE;

    return ring->u16WItemID;
}

int32_t wl_ringbuf_writeOver(Ringbuf_st* ring, uint8_t* data, uint32_t size)
{
    if (ring == NULL || data ==NULL || size == 0 || size+DMA_DATALEN_LEN > ring->u16ItemSize)
    {
        return ERR_RINGBUF_INVALID_PARAM;
    }

    if (ring->u8WritingFlag == TRUE)
    {
        return ERR_RINGBUF_WRITE_BUSY;
    }

    if (ring->u16FullFlag == TRUE)
    {
        ring->u16RItemID = (ring->u16RItemID+1)%ring->u16RItemID;
    }

    ring->u8WritingFlag = TRUE;
    memset((uint8_t*)&ring->ps8Buf[ring->u16WItemID*ring->u16ItemSize], 0, ring->u16ItemSize);
    memcpy((uint8_t*)&ring->ps8Buf[ring->u16WItemID*ring->u16ItemSize], (uint8_t*)&size, DMA_DATALEN_LEN);
    memcpy((uint8_t*)&ring->ps8Buf[ring->u16WItemID*ring->u16ItemSize+DMA_DATALEN_LEN], data, size);
    ring->u16WItemID = (ring->u16WItemID+1)%ring->u16Items;

    if (ring->u16WItemID == ring->u16RItemID)
    {
        ring->u16FullFlag = TRUE;
    }

    ring->leftItem = wl_ringbuf_freeSize(ring);
    if (ring->minLeftItem > ring->leftItem)
    {
        ring->minLeftItem = ring->leftItem;
    }

    ring->u8WritingFlag = FALSE;

    return ring->u16WItemID;
}

int32_t wl_ringbuf_read(Ringbuf_st* ring, uint8_t* data, uint32_t* size)
{
    if (ring == NULL || data ==NULL || size == NULL)
    {
        return ERR_RINGBUF_INVALID_PARAM;
    }

    if (ring->u8ReadingFlag == TRUE)
    {
        return ERR_RINGBUF_READ_BUSY;
    }

    if (ring->u16WItemID == ring->u16RItemID && ring->u16FullFlag == FALSE)
    {
        return ERR_RINGBUF_BUF_EMPTY;
    }

    ring->u8ReadingFlag = TRUE;
    *size = ring->ps8Buf[ring->u16RItemID*ring->u16ItemSize];
    memcpy((uint8_t*)size, (uint8_t*)&ring->ps8Buf[ring->u16RItemID*ring->u16ItemSize], DMA_DATALEN_LEN);
    memcpy(data, (uint8_t*)&ring->ps8Buf[ring->u16RItemID*ring->u16ItemSize+DMA_DATALEN_LEN], *size);
    ring->u16RItemID = (ring->u16RItemID+1)%ring->u16Items;
    ring->u16FullFlag = FALSE;
    ring->u8ReadingFlag = FALSE;

    return ring->u16RItemID;
}


uint16_t wl_ringbuf_containSize(Ringbuf_st* ring)
{
    if (ring->u16FullFlag == TRUE)
    {
        return ring->u16Items;
    }

    return (ring->u16Items+ring->u16WItemID-ring->u16RItemID)%ring->u16Items;
}

uint16_t wl_ringbuf_freeSize(Ringbuf_st* ring)
{
    return ring->u16Items-wl_ringbuf_containSize(ring);
}

int32_t wl_ringbuf_clear(Ringbuf_st* ring)
{
    if (ring == NULL)
    {
        return ERR_RINGBUF_INVALID_PARAM;
    }

    if (ring->u8ReadingFlag == TRUE)
    {
       return ERR_RINGBUF_READ_BUSY;
    }
   if (ring->u8WritingFlag == TRUE)
    {
        return ERR_RINGBUF_WRITE_BUSY;
    }

    ring->u16RItemID = 0;
    ring->u16WItemID = 0;
    ring->u16FullFlag   = FALSE;
    ring->u8ReadingFlag = FALSE;
    ring->u8WritingFlag = FALSE;
            
    return 0;

}
